package org.eiahe.hr.performance.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.ehe.common.core.exception.ServiceException;
import org.ehe.common.core.utils.MapstructUtils;
import org.ehe.common.core.utils.StringUtils;
import org.ehe.system.domain.SysPost;
import org.ehe.system.mapper.SysPostMapper;
import org.eiahe.hr.performance.domain.PerformanceIndicator;
import org.eiahe.hr.performance.domain.PerformancePositionIndicator;
import org.eiahe.hr.performance.domain.bo.PerformancePositionIndicatorBo;
import org.eiahe.hr.performance.domain.bo.PerformancePositionIndicatorQueryBo;
import org.eiahe.hr.performance.domain.vo.PerformancePositionIndicatorVo;
import org.eiahe.hr.performance.mapper.PerformancePositionIndicatorMapper;
import org.eiahe.hr.performance.service.IPerformanceIndicatorService;
import org.eiahe.hr.performance.service.IPerformancePositionIndicatorService;
import org.ehe.system.domain.vo.SysPostVo;
import org.ehe.common.mybatis.core.page.PageQuery;
import org.ehe.common.mybatis.core.page.TableDataInfo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 岗位指标关联Service业务层处理
 *
 * @author zhangnn
 */
@RequiredArgsConstructor
@Service
public class PerformancePositionIndicatorServiceImpl
        extends ServiceImpl<PerformancePositionIndicatorMapper, PerformancePositionIndicator>
        implements IPerformancePositionIndicatorService {

    private final PerformancePositionIndicatorMapper baseMapper;
    private final SysPostMapper postMapper;
    private final IPerformanceIndicatorService indicatorService;

    @Override
    public PerformancePositionIndicatorVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    @Override
    public TableDataInfo<PerformancePositionIndicatorVo> queryPageListVoByCondition(
            PerformancePositionIndicatorQueryBo queryBo, PageQuery pageQuery) {
        LambdaQueryWrapper<PerformancePositionIndicator> lqw = buildQueryWrapper(queryBo);
        Page<PerformancePositionIndicatorVo> performancePositionIndicatorIPage = this.baseMapper
                .selectVoPage(pageQuery.build(), lqw);
        performancePositionIndicatorIPage.getRecords().forEach(p -> {
            SysPostVo sysPostVo = postMapper.selectVoById(p.getPositionId());
            if (Objects.nonNull(sysPostVo)) {
                p.setPositionName(sysPostVo.getPostName());
            }
            PerformanceIndicator indicator = indicatorService.queryById(p.getIndicatorId());
            if (Objects.nonNull(indicator)) {
                p.setIndicatorName(indicator.getIndicatorName());
            }
        });
        return TableDataInfo.build(performancePositionIndicatorIPage);
    }

    private LambdaQueryWrapper<PerformancePositionIndicator> buildQueryWrapper(PerformancePositionIndicatorQueryBo bo) {
        LambdaQueryWrapper<PerformancePositionIndicator> lqw = Wrappers.lambdaQuery();
        List<Long> indIds = new ArrayList<>();
        if (StringUtils.isNotBlank(bo.getIndicatorName())) {
            List<PerformanceIndicator> indicators = indicatorService.list(new LambdaQueryWrapper<PerformanceIndicator>()
                    .like(PerformanceIndicator::getIndicatorName, bo.getIndicatorName()));

            if (Objects.nonNull(indicators)) {
                indIds = indicators.stream().map(PerformanceIndicator::getIndicatorId).collect(Collectors.toList());
            } else {
                indIds.add(-1L);
            }
        }

        List<Long> postIds = new ArrayList<>();
        if (StringUtils.isNotBlank(bo.getPositionName())) {
            List<SysPostVo> postVos = postMapper.selectVoList(new LambdaQueryWrapper<SysPost>()
                    .like(SysPost::getPostName, bo.getPositionName()));

            if (Objects.nonNull(postVos)) {
                postIds = postVos.stream().map(SysPostVo::getPostId).collect(Collectors.toList());
            } else {
                postIds.add(-1L);
            }
        }

        lqw.in(CollUtil.isNotEmpty(indIds), PerformancePositionIndicator::getIndicatorId, indIds);
        lqw.in(CollUtil.isNotEmpty(postIds), PerformancePositionIndicator::getPositionId, postIds);

        // 添加level筛选条件
        if (bo.getLevel() != null) {
            lqw.eq(PerformancePositionIndicator::getLevel, bo.getLevel());
        }

        lqw.orderByAsc(PerformancePositionIndicator::getCreateTime);
        return lqw;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(PerformancePositionIndicatorBo indicator) {
        // 设置默认值
        if (indicator.getLevel() == null) {
            indicator.setLevel(1);
        }

        // 验证权重
        validatePositionIndicatorWeight(indicator.getPositionId(), indicator.getWeight(), null);

        // 如果关联的是父级指标，自动创建子指标关联
        handleChildIndicators(indicator);

        PerformancePositionIndicator add = MapstructUtils.convert(indicator, PerformancePositionIndicator.class);
        boolean result = baseMapper.insert(add) > 0;

        // 清除缓存
        if (result) {
            clearPositionCache(indicator.getPositionId());
        }

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(PerformancePositionIndicatorBo indicator) {
        // 验证权重
        validatePositionIndicatorWeight(indicator.getPositionId(), indicator.getWeight(), indicator.getId());

        // 如果关联的是父级指标，自动更新子指标关联
        handleChildIndicators(indicator);

        PerformancePositionIndicator update = MapstructUtils.convert(indicator, PerformancePositionIndicator.class);
        boolean result = baseMapper.updateById(update) > 0;

        // 清除缓存
        if (result) {
            clearPositionCache(indicator.getPositionId());
        }

        return result;
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (ids == null || ids.isEmpty()) {
            return false;
        }
        if (isValid) {
            // 校验逻辑可以根据需要添加
        }

        // 获取要删除的记录的岗位ID，用于清除缓存
        List<Long> positionIds = new ArrayList<>();
        for (Long id : ids) {
            PerformancePositionIndicator indicator = baseMapper.selectById(id);
            if (indicator != null) {
                positionIds.add(indicator.getPositionId());
            }
        }

        boolean result = baseMapper.deleteBatchIds(ids) > 0;

        // 清除缓存
        if (result) {
            for (Long positionId : positionIds) {
                clearPositionCache(positionId);
            }
        }

        return result;
    }

    /**
     * 清除岗位缓存
     * 
     * @param positionId 岗位ID
     */
    private void clearPositionCache(Long positionId) {
        // 这里可以调用缓存服务清除缓存
        // 暂时留空，后续可以集成缓存服务
    }

    /**
     * 校验岗位指标权重总和
     */
    private void validatePositionIndicatorWeight(Long positionId, BigDecimal newWeight, Long excludeId) {
        LambdaQueryWrapper<PerformancePositionIndicator> lqw = Wrappers.lambdaQuery();
        lqw.eq(PerformancePositionIndicator::getPositionId, positionId);
        lqw.eq(PerformancePositionIndicator::getDelFlag, "0");
        if (excludeId != null) {
            lqw.ne(PerformancePositionIndicator::getId, excludeId);
        }

        List<PerformancePositionIndicator> list = baseMapper.selectList(lqw);
        BigDecimal totalWeight = list.stream()
                .map(PerformancePositionIndicator::getWeight)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        totalWeight = totalWeight.add(newWeight != null ? newWeight : BigDecimal.ZERO);

        if (totalWeight.compareTo(new BigDecimal("100")) > 0) {
            throw new ServiceException("岗位指标权重总和不能超过100%，当前已分配：" + totalWeight);
        }
    }

    /**
     * 处理子指标关联
     * 如果关联的是父级指标，则自动为所有子指标创建关联关系
     */
    private void handleChildIndicators(PerformancePositionIndicatorBo parentIndicator) {
        // 查询指标信息
        PerformanceIndicator indicator = indicatorService.queryById(parentIndicator.getIndicatorId());
        if (indicator == null) {
            throw new ServiceException("指标不存在");
        }

        // 如果是父级指标（level > 1），则需要处理子指标
        if (indicator.getLevel() != null && indicator.getLevel() > 0) {
            // 查询所有子指标
            List<PerformanceIndicator> childIndicators = indicatorService
                    .list(new LambdaQueryWrapper<PerformanceIndicator>()
                            .eq(PerformanceIndicator::getParentId, indicator.getIndicatorId())
                            .eq(PerformanceIndicator::getDelFlag, "0"));

            // 为每个子指标创建岗位关联
            for (PerformanceIndicator child : childIndicators) {
                // 检查是否已存在关联
                LambdaQueryWrapper<PerformancePositionIndicator> checkLqw = Wrappers.lambdaQuery();
                checkLqw.eq(PerformancePositionIndicator::getPositionId, parentIndicator.getPositionId());
                checkLqw.eq(PerformancePositionIndicator::getIndicatorId, child.getIndicatorId());
                checkLqw.eq(PerformancePositionIndicator::getDelFlag, "0");

                PerformancePositionIndicator existing = baseMapper.selectOne(checkLqw);

                if (existing == null) {
                    // 创建子指标关联
                    PerformancePositionIndicatorBo childPositionIndicator = new PerformancePositionIndicatorBo();
                    childPositionIndicator.setPositionId(parentIndicator.getPositionId());
                    childPositionIndicator.setIndicatorId(child.getIndicatorId());
                    childPositionIndicator.setLevel(indicator.getLevel() + 1);
                    childPositionIndicator.setParentPositionIndicatorId(parentIndicator.getId());
                    childPositionIndicator
                            .setWeight(calculateChildWeight(parentIndicator.getWeight(), child.getWeight()));

                    PerformancePositionIndicator add = MapstructUtils.convert(childPositionIndicator,
                            PerformancePositionIndicator.class);
                    baseMapper.insert(add);
                }
            }
        }
    }

    /**
     * 计算子指标权重
     * 子指标权重 = 父指标权重 × (子指标在父指标中的占比)
     */
    private BigDecimal calculateChildWeight(BigDecimal parentWeight, BigDecimal childPercentage) {
        if (parentWeight == null || childPercentage == null) {
            return BigDecimal.ZERO;
        }

        // childPercentage是子指标在其父指标中的占比（0-100%）
        // 最终权重 = 父权重 × (子指标占比 / 100)
        return parentWeight.multiply(childPercentage).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 查询岗位指标树状结构
     */
    @Override
    public List<PerformancePositionIndicatorVo> getPositionIndicatorTree(Long positionId) {
        // 查询该岗位的所有指标关联
        LambdaQueryWrapper<PerformancePositionIndicator> lqw = Wrappers.lambdaQuery();
        lqw.eq(PerformancePositionIndicator::getPositionId, positionId);
        lqw.eq(PerformancePositionIndicator::getDelFlag, "0");
        lqw.orderByAsc(PerformancePositionIndicator::getLevel);

        List<PerformancePositionIndicator> positionIndicators = baseMapper.selectList(lqw);

        // 转换为VO并补充指标信息
        List<PerformancePositionIndicatorVo> voList = positionIndicators.stream().map(indicator -> {
            PerformancePositionIndicatorVo vo = new PerformancePositionIndicatorVo();
            vo.setId(indicator.getId());
            vo.setPositionId(indicator.getPositionId());
            vo.setIndicatorId(indicator.getIndicatorId());
            vo.setLevel(indicator.getLevel());
            vo.setParentPositionIndicatorId(indicator.getParentPositionIndicatorId());
            vo.setWeight(indicator.getWeight());

            // 补充指标名称
            PerformanceIndicator perfIndicator = indicatorService.queryById(indicator.getIndicatorId());
            if (perfIndicator != null) {
                vo.setIndicatorName(perfIndicator.getIndicatorName());
            }

            return vo;
        }).collect(Collectors.toList());

        // 构建树状结构
        return buildTree(voList, null);
    }

    /**
     * 构建树状结构
     */
    private List<PerformancePositionIndicatorVo> buildTree(List<PerformancePositionIndicatorVo> list, Long parentId) {
        return list.stream()
                .filter(item -> (parentId == null && item.getParentPositionIndicatorId() == null) ||
                        (parentId != null && parentId.equals(item.getParentPositionIndicatorId())))
                .peek(item -> item.setChildren(buildTree(list, item.getId())))
                .collect(Collectors.toList());
    }

    /**
     * 计算加权得分
     * 
     * @param score  原始分数
     * @param weight 权重
     * @return 加权得分
     */
    public BigDecimal calculateWeightedScore(BigDecimal score, BigDecimal weight) {
        if (score == null || weight == null) {
            return BigDecimal.ZERO;
        }

        return score.multiply(weight).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
    }

    /**
     * 获取岗位指标权重
     * 
     * @param positionId  岗位ID
     * @param indicatorId 指标ID
     * @return 权重值
     */
    public BigDecimal getPositionIndicatorWeight(Long positionId, Long indicatorId) {
        if (positionId == null || indicatorId == null) {
            return BigDecimal.ZERO;
        }

        LambdaQueryWrapper<PerformancePositionIndicator> lqw = Wrappers.lambdaQuery();
        lqw.eq(PerformancePositionIndicator::getPositionId, positionId);
        lqw.eq(PerformancePositionIndicator::getIndicatorId, indicatorId);
        lqw.eq(PerformancePositionIndicator::getDelFlag, "0");

        PerformancePositionIndicator positionIndicator = baseMapper.selectOne(lqw);
        return positionIndicator != null ? positionIndicator.getWeight() : BigDecimal.ZERO;
    }

    /**
     * 获取岗位所有直接关联的指标（不包括继承的子指标）
     * 
     * @param positionId 岗位ID
     * @return 指标列表
     */
    public List<PerformancePositionIndicator> getDirectPositionIndicators(Long positionId) {
        if (positionId == null) {
            return new ArrayList<>();
        }

        LambdaQueryWrapper<PerformancePositionIndicator> lqw = Wrappers.lambdaQuery();
        lqw.eq(PerformancePositionIndicator::getPositionId, positionId);
        lqw.eq(PerformancePositionIndicator::getLevel, 1); // 只查询直接关联的指标
        lqw.eq(PerformancePositionIndicator::getDelFlag, "0");
        lqw.orderByAsc(PerformancePositionIndicator::getCreateTime);

        return baseMapper.selectList(lqw);
    }

    /**
     * 获取岗位指标的完整层级结构
     * 
     * @param positionId 岗位ID
     * @return 指标树状结构
     */
    public List<PerformancePositionIndicatorVo> getFullPositionIndicatorTree(Long positionId) {
        // 获取所有关联指标
        LambdaQueryWrapper<PerformancePositionIndicator> lqw = Wrappers.lambdaQuery();
        lqw.eq(PerformancePositionIndicator::getPositionId, positionId);
        lqw.eq(PerformancePositionIndicator::getDelFlag, "0");
        lqw.orderByAsc(PerformancePositionIndicator::getLevel);

        List<PerformancePositionIndicator> positionIndicators = baseMapper.selectList(lqw);

        // 转换为VO并补充指标信息
        List<PerformancePositionIndicatorVo> voList = positionIndicators.stream().map(indicator -> {
            PerformancePositionIndicatorVo vo = new PerformancePositionIndicatorVo();
            vo.setId(indicator.getId());
            vo.setPositionId(indicator.getPositionId());
            vo.setIndicatorId(indicator.getIndicatorId());
            vo.setLevel(indicator.getLevel());
            vo.setParentPositionIndicatorId(indicator.getParentPositionIndicatorId());
            vo.setWeight(indicator.getWeight());

            // 补充指标名称
            PerformanceIndicator perfIndicator = indicatorService.queryById(indicator.getIndicatorId());
            if (perfIndicator != null) {
                vo.setIndicatorName(perfIndicator.getIndicatorName());
            }

            return vo;
        }).collect(Collectors.toList());

        // 构建树状结构
        return buildTree(voList, null);
    }

}